package com.sxf.core.validator;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.math.BigDecimal;

/**
 * Check 数字多种范围判断.
 *
 * @author SSLi
 */
public class AllowedNumberRangeValidator implements ConstraintValidator<AllowedNumberRange, Number> {

    private BigDecimal max;
    private BigDecimal min;
    private boolean maxInclusive;
    private boolean minInclusive;
    private int maxIntegerLength;
    private int maxFractionLength;
    private boolean checkNull;
    private boolean negative;

    @Override
    public void initialize(AllowedNumberRange allowedNumberRange) {
        try {
            this.max = BigDecimal.valueOf(allowedNumberRange.max());
            this.min = BigDecimal.valueOf(allowedNumberRange.min());
        } catch (NumberFormatException nfe) {
            throw new IllegalArgumentException("数字格式异常");
        }
        this.maxInclusive = allowedNumberRange.maxInclusive();
        this.minInclusive = allowedNumberRange.minInclusive();
        this.maxIntegerLength = allowedNumberRange.integer();
        this.maxFractionLength = allowedNumberRange.fraction();
        validateParameters();
        this.checkNull = allowedNumberRange.checkNull();
        this.negative = allowedNumberRange.negative();
    }

    @Override
    public boolean isValid(Number num, ConstraintValidatorContext constraintValidatorContext) {
        //null values are valid
        if (!checkNull && num == null) {
            return true;
        }
        if (num == null) {
            return false;
        }
        BigDecimal bigNum;
        if (num instanceof BigDecimal) {
            bigNum = ((BigDecimal) num).stripTrailingZeros();
        } else {
            try {
                bigNum = new BigDecimal(num.toString()).stripTrailingZeros();
            } catch (NumberFormatException nfe) {
                return false;
            }
        }
        //不允许负数
        if (!negative && bigNum.compareTo(BigDecimal.ZERO) < 0) {
            return false;
        }
        int integerPartLength = bigNum.precision() - bigNum.scale();
        int fractionPartLength = Math.max(bigNum.scale(), 0);
        //位数不符合
        if (!(maxIntegerLength >= integerPartLength && maxFractionLength >= fractionPartLength)) {
            return false;
        }
        //判断大小
        int minComparisonResult = bigNum.compareTo(min);
        int maxComparisonResult = bigNum.compareTo(max);
        return (minInclusive ? minComparisonResult >= 0 : minComparisonResult > 0) && (maxInclusive ? maxComparisonResult <= 0 : maxComparisonResult < 0);
    }


    private void validateParameters() {
        if (maxIntegerLength < 0) {
            throw new IllegalArgumentException("最大整数位不得小于0");
        }
        if (maxFractionLength < 0) {
            throw new IllegalArgumentException("最大小数位不得小于0");
        }
    }
}
